home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / wnos / wn941101 / tcpcmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-03  |  11.6 KB  |  488 lines

  1. /* 
  2.  * 941003 added TCP access control dc0hk
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include "global.h"
  7. #include "timer.h"
  8. #include "mbuf.h"
  9. #include "netuser.h"
  10. #include "internet.h"
  11. #include "tcp.h"
  12. #include "cmdparse.h"
  13. #include "commands.h"
  14. #include "config.h"
  15.  
  16. #ifdef  TCPACCESS
  17. static int doaccess __ARGS((int argc,char *argv[],void *p));
  18. void addtaccess __ARGS((int32 target,unsigned int bits,int16 low,int16 high,int16 permit));
  19. struct rtaccess *TCPaccess = NULLACCESS; /* access list */
  20. #endif
  21.  
  22. /* Close a TCP connection */
  23. static int
  24. dotcpclose(argc,argv,p)
  25. int argc;
  26. char *argv[];
  27. void *p;
  28. {
  29.     struct tcb *tcb = (struct tcb *)ltop(htol(argv[1]));
  30.  
  31.     if(!tcpval(tcb)) {
  32.         tputs(Notval);
  33.         return 1;
  34.     }
  35.     return close_tcp(tcb);
  36. }
  37.  
  38. /* Set initial round trip time for new connections */
  39. static int
  40. doirtt(argc,argv,p)
  41. int argc;
  42. char *argv[];
  43. void *p;
  44. {
  45.     struct tcp_rtt *tp;
  46.  
  47.     setlong(&Tcp_irtt,"TCP irtt",argc,argv);
  48.  
  49.     if(argc < 2){
  50.       for(tp = &Tcp_rtt[0];tp < &Tcp_rtt[RTTCACHE];tp++) {
  51.         if(tp->addr != 0) {
  52.           if(tprintf("%s: srtt %ld mdev %ld\n",
  53.             inet_ntoa(tp->addr),tp->srtt,tp->mdev) == EOF)
  54.               break;
  55.         }
  56.       }
  57.     }
  58.     return 0;
  59. }
  60.  
  61. /* Force a retransmission */
  62. static int
  63. dotcpkick(argc,argv,p)
  64. int argc;
  65. char *argv[];
  66. void *p;
  67. {
  68.     struct tcb *tcb = (struct tcb *)ltop(htol(argv[1]));
  69.  
  70.     if(kick_tcp(tcb) == -1){
  71.         tputs(Notval);
  72.         return 1;
  73.     }
  74.     return 0;
  75. }
  76.  
  77. /* Set default maximum segment size */
  78. static int
  79. domss(argc,argv,p)
  80. int argc;
  81. char *argv[];
  82. void *p;
  83. {
  84.     return setshort(&Tcp_mss,"TCP MSS",argc,argv);
  85. }
  86.  
  87. /* Eliminate a TCP connection */
  88. static int
  89. dotcpreset(argc,argv,p)
  90. int argc;
  91. char *argv[];
  92. void *p;
  93. {
  94.     struct tcb *tcb = (struct tcb *)ltop(htol(argv[1]));
  95.  
  96.     if(!tcpval(tcb)){
  97.         tputs(Notval);
  98.         return 1;
  99.     }
  100.     close_self(tcb,RESET);
  101.     return 0;
  102. }
  103.  
  104. static int
  105. dotcpretry(argc,argv,p)
  106. int argc;
  107. char *argv[];
  108. void *p;
  109. {
  110.     extern int Tcp_retry;
  111.  
  112.     return setint(&Tcp_retry,"TCP retry",argc,argv);
  113. }
  114.  
  115. /* Set smoothed round trip time for specified TCB */
  116. static int
  117. dortt(argc,argv,p)
  118. int argc;
  119. char *argv[];
  120. void *p;
  121. {
  122.     struct tcb *tcb = (struct tcb *)ltop(htol(argv[1]));
  123.  
  124.     if(!tcpval(tcb)){
  125.         tputs(Notval);
  126.         return 1;
  127.     }
  128.     tcb->srtt = atol(argv[2]);
  129.     return 0;
  130. }
  131.  
  132. /* Display status of TCBs */
  133. static int
  134. dotcpstat(argc,argv,p)
  135. int argc;
  136. char *argv[];
  137. void *p;
  138. {
  139.   if(argc < 2) {
  140.   /* Dump TCP stats and summary of all TCBs
  141.   /*     &TCB Rcv-Q Snd-Q  Local socket           Remote socket          State
  142.    *     1234     0     0  xxx.xxx.xxx.xxx:xxxxx  xxx.xxx.xxx.xxx:xxxxx  Established
  143.    */
  144.     int i, j;
  145.     struct tcb *tcb;
  146.  
  147.     for(j = i = 1; i <= NUMTCPMIB; i++) {
  148.       if(Tcp_mib[i].name == NULLCHAR)
  149.         continue;
  150.       tprintf("(%2u)tcp%-17s%10lu",i,Tcp_mib[i].name,Tcp_mib[i].value.integer);
  151.       tputs((j++ % 2) ? "     " : "\n");
  152.     }
  153.     if((j % 2) == 0)
  154.       tputs("\n");
  155.  
  156.     tputs("&TCB     Rcv-Q Snd-Q  Local socket           Remote socket          State\n");
  157.     for(tcb = Tcbs; tcb != NULLTCB; tcb = tcb->next){
  158.       tprintf("%8lx%6u%6u  ",ptol(tcb),tcb->rcvcnt,tcb->sndcnt);
  159.       tprintf("%-23s",pinet(&tcb->conn.local));
  160.       tprintf("%-23s%-s",pinet(&tcb->conn.remote),Tcpstates[tcb->state]);
  161.       if(tcb->state == TCP_LISTEN && tcb->flags.clone)
  162.         tputs(" (S)");
  163.       tputs("\n");
  164.     }
  165.   } else {
  166.     struct tcb *tcb = (struct tcb *)ltop(htol(argv[1]));
  167.     if(tcpval(tcb))
  168.       st_tcp(tcb);
  169.     else
  170.       tputs(Notval);
  171.   }
  172.   return 0;
  173. }
  174.  
  175. static int
  176. dosyndata(argc,argv,p)
  177. int argc;
  178. char *argv[];
  179. void *p;
  180. {
  181.     return setbool(&Tcp_syndata,"TCP syn+data piggybacking",argc,argv);
  182. }
  183.  
  184. static int
  185. dotcptr(argc,argv,p)
  186. int argc;
  187. char *argv[];
  188. void *p;
  189. {
  190.     return setbool(&Tcp_trace,"TCP trace",argc,argv);
  191. }
  192.  
  193. /* Set default window size */
  194. static int
  195. dowindow(argc,argv,p)
  196. int argc;
  197. char *argv[];
  198. void *p;
  199. {
  200.     return setshort(&Tcp_window,"TCP window",argc,argv);
  201. }
  202.  
  203. /* Dump a TCP control block in detail */
  204. void
  205. st_tcp(tcb)
  206. struct tcb *tcb;
  207. {
  208.     int32 sent, recvd;
  209.  
  210.     if(tcb == NULLTCB)
  211.         return;
  212.  
  213.     /* Compute total data sent and received; take out SYN and FIN */
  214.     sent = tcb->snd.una - tcb->iss;    /* Acknowledged data only */
  215.     recvd = tcb->rcv.nxt - tcb->irs;
  216.  
  217.     switch(tcb->state){
  218.     case TCP_LISTEN:
  219.     case TCP_SYN_SENT:    /* Nothing received or acked yet */
  220.         sent = recvd = 0;
  221.         break;
  222.     case TCP_SYN_RECEIVED:
  223.         recvd--;    /* Got SYN, no data acked yet */
  224.         sent = 0;
  225.         break;
  226.     case TCP_ESTABLISHED:    /* Got and sent SYN */
  227.     case TCP_FINWAIT1:    /* FIN not acked yet */
  228.         sent--;
  229.         recvd--;
  230.         break;
  231.     case TCP_FINWAIT2:    /* Our SYN and FIN both acked */
  232.         sent -= 2;
  233.         recvd--;
  234.         break;
  235.     case TCP_CLOSE_WAIT:    /* Got SYN and FIN, our FIN not yet acked */
  236.     case TCP_CLOSING:
  237.     case TCP_LAST_ACK:
  238.         sent--;
  239.         recvd -= 2;
  240.         break;
  241.     case TCP_TIME_WAIT:    /* Sent and received SYN/FIN, all acked */
  242.         sent -= 2;
  243.         recvd -= 2;
  244.         break;
  245.     }
  246.     tprintf("Local %s",pinet(&tcb->conn.local));
  247.     tprintf(" Remote %s",pinet(&tcb->conn.remote));
  248.     tprintf(" State: %s\n      Init seq    Unack     Next Resent CWind "
  249.         "Thrsh  Wind  MSS Queue      Total\n",Tcpstates[tcb->state]);
  250.     tprintf("Send:%9lx%9lx%9lx",tcb->iss,tcb->snd.una,tcb->snd.nxt);
  251.     tprintf("%7lu%6u%6u",tcb->resent,tcb->cwind,tcb->ssthresh);
  252.     tprintf("%6u%5u%6u%11lu\n",tcb->snd.wnd,tcb->mss,tcb->sndcnt,sent);
  253.  
  254.     tprintf("Recv:%9lx%18lx%7lu",tcb->irs,tcb->rcv.nxt,tcb->rerecv);
  255.     tprintf("%18u%11u%11lu\n",tcb->rcv.wnd,tcb->rcvcnt,recvd);
  256.  
  257.     if(tcb->backoff > 0)
  258.         tprintf("Backoff %u ",tcb->backoff);
  259.     if(tcb->flags.retran)
  260.         tputs("Retrying ");
  261.     tputs("Timer ");
  262.     switch(tcb->timer.state){
  263.     case TIMER_STOP:
  264.         tputs("-");
  265.         break;
  266.     case TIMER_RUN:
  267.         tprintf("%lu",read_timer(&tcb->timer));
  268.         break;
  269.     case TIMER_EXPIRE:
  270.         tputs("E");
  271.     }
  272.  
  273.     tprintf("/%lu ms SRTT %ld ms Mean dev %ld ms\n",
  274.         dur_timer(&tcb->timer),tcb->srtt,tcb->mdev);
  275.  
  276.     if(tcb->reseq != (struct reseq *)NULL){
  277.         struct reseq *rp;
  278.  
  279.         tputs("Reassembly queue:\n");
  280.         for(rp = tcb->reseq;rp != (struct reseq *)NULL; rp = rp->next){
  281.             if(tprintf("  seq x%lx %u bytes\n",
  282.              rp->seg.seq,rp->length) == EOF)
  283.                 return;
  284.         }
  285.     }
  286. }
  287.  
  288. #ifdef  TCPACCESS
  289. static int
  290. doaccess(argc,argv,p)
  291. int argc;
  292. char *argv[];
  293. void *p;
  294. {
  295.     struct iface *ifp;
  296.     int32 target;
  297.     unsigned bits;
  298.     char *bitp;
  299.     int16 lport,hport,state;
  300.     char *cp; /* for printing the table */
  301.     struct rtaccess *tpacc;
  302.     struct rtaccess *head;
  303.     struct rtaccess *prev;
  304.   
  305.     if(argc == 1){ /* print out the table */
  306.         tputs("IP Address      Mask  Low Port High Port State\n");
  307.         for(tpacc = TCPaccess;tpacc != NULLACCESS;tpacc = tpacc->nxtbits){
  308.             if(tpacc->target != 0)
  309.                 cp = inet_ntoa(tpacc->target);
  310.             else
  311.                 cp = "all";
  312.             tprintf("%-16s",cp);
  313.             tprintf("%4u ",tpacc->bits);
  314.             tprintf("%9u",tpacc->lowport);
  315.             tprintf("%10u ",tpacc->highport);
  316.             if(tpacc->status)
  317.                 cp = "deny";
  318.             else
  319.                 cp = "permit";
  320.             tprintf("%-6s\n",cp);
  321.         }
  322.         return 0;
  323.     }
  324.   
  325.     if(strcmp(argv[1],"permit") == 0){
  326.         state = 0;
  327.     } else {
  328.         if((strcmp(argv[1],"deny") == 0)
  329.         || (strcmp(argv[1],"delete") == 0)){
  330.             state = -1;
  331.         } else {
  332.             tputs("Format: tcp access <permit|deny|delete> <dest addr>[/<bits>] [low [high]|ALL]\n");
  333.             return 1;
  334.         }
  335.     }
  336.     if(strcmp(argv[2],"all") == 0){
  337.         target = 0;
  338.         bits = 0;
  339.     } else {
  340.         /* If IP address is followed by an optional slash and
  341.          * a length field, (e.g., 128.96/16) get it;
  342.          * otherwise assume a full 32-bit address
  343.          */
  344.         if((bitp = strchr(argv[2],'/')) != NULLCHAR){
  345.             /* Terminate address token for resolve() call */
  346.             *bitp++ = '\0';
  347.             bits = atoi(bitp);
  348.         } else
  349.             bits = 32;
  350.   
  351.         if((target = resolve(argv[2])) == 0){
  352.             tprintf(Badhost,argv[2]);
  353.             return 1;
  354.         }
  355.     }
  356.   
  357.     if(argc > 3){
  358.         if(strcmp(argv[3],"all") == 0){
  359.             lport = 1;
  360.             hport = 65534L;
  361.         } else {
  362.             lport = atoi(argv[3]);
  363.             hport = lport;
  364.         }
  365.     } else {
  366.         lport = 0;
  367.         hport = 0;
  368.     }
  369.     if(argc > 4)
  370.         hport = atoi(argv[4]);
  371.   
  372.     if(strcmp(argv[1],"delete") == 0){
  373.         prev = NULLACCESS;
  374.         head = tpacc = TCPaccess;
  375.         while(tpacc != NULLACCESS){
  376.             head = tpacc;
  377.             tpacc = tpacc->nxtbits;
  378.             if((head->target == target) &&
  379.                 (head->bits == bits)     &&
  380.                 (head->lowport == lport) &&
  381.             (head->highport == hport)) { /*match*/
  382.   
  383.   
  384.                 /*now delete. watch for special cases*/
  385.                 if(head == TCPaccess) /* first in chain */
  386.                     TCPaccess = head->nxtbits;
  387.                 else
  388.                     /*
  389.                       sanity check: we cant get here with
  390.                       prev == NULLACCESS !!
  391.                      */
  392.                     prev->nxtbits = tpacc;
  393.                 free(head);
  394.                 return 0;
  395.             }
  396.             prev = head;
  397.         }
  398.         tputs("Not found.\n");
  399.         return 1;
  400.     }
  401.     /* add the access */
  402.     addtaccess(target,bits,lport,hport,state);
  403.     return 0;
  404. }
  405. /* add an entry to the access control list */
  406. /* not a lot of error checking 8-) */
  407. void
  408. addtaccess(target,bits,low,high,permit)
  409. int32 target;           /* Target IP address prefix */
  410. unsigned int bits;      /* Size of target address prefix in bits (0-32) */
  411. int16 low;
  412. int16 high;
  413. int16 permit;
  414. {
  415.     struct rtaccess *tpacc; /*temporary*/
  416.     struct rtaccess *holder; /*for the new record*/
  417.   
  418.     holder = (struct rtaccess *)mxallocw(sizeof(struct rtaccess));
  419.     holder->nxtiface = NULLACCESS;
  420.     holder->nxtbits = NULLACCESS;
  421.     holder->target = target;
  422.     holder->bits = bits;
  423.     holder->lowport = low;
  424.     holder->highport = high;
  425.     holder->status = permit;
  426.     if((tpacc = TCPaccess) == NULLACCESS){
  427.         TCPaccess = holder;
  428.     } else {
  429.         while(tpacc->nxtbits != NULLACCESS)
  430.             tpacc = tpacc->nxtbits;
  431.         tpacc->nxtbits = holder;
  432.     }
  433. }
  434.  
  435. /* check to see if port is "authorized".  Returns 0 if matching permit record
  436.    is found or no access records exists, -1 if not found or deny record found */
  437. int
  438. tcp_check(accptr,src,port)
  439. struct rtaccess *accptr;
  440. int32 src;
  441. int16 port;
  442. {
  443.     unsigned long mask;
  444.   
  445.     if(accptr == NULLACCESS)
  446.         return 0;               /* no access control */
  447.     for(;accptr != NULLACCESS;accptr = accptr->nxtbits) {
  448.         mask = ~0L << (32 - accptr->bits);
  449.         if(( accptr->target == (mask & src)) &&
  450.             ((( port >= accptr->lowport ) && (port <= accptr->highport))
  451.         || (!accptr->lowport))){
  452.             return (accptr->status);
  453.         }
  454.     }
  455.     return -1; /* fall through to here if not found */
  456. }
  457.  
  458. #endif /* TCPACCESS */
  459.  
  460.  
  461. /* TCP subcommand table */
  462. int
  463. dotcp(argc,argv,p)
  464. int argc;
  465. char *argv[];
  466. void *p;
  467. {
  468.     struct cmds Tcpcmds[] = {
  469. #ifdef  TCPACCESS
  470.         "access",       doaccess,       0,      0, NULLCHAR,
  471. #endif
  472.         "close",    dotcpclose,     0, 2,    "tcp close <tcb>",
  473.         "irtt",        doirtt,            0, 0,    NULLCHAR,
  474.         "kick",        dotcpkick,        0, 2,    "tcp kick <tcb>",
  475.         "mss",        domss,            0, 0,    NULLCHAR,
  476.         "reset",    dotcpreset,        0, 2,    "tcp reset <tcb>",
  477.         "retry",    dotcpretry,     0, 0,    NULLCHAR,
  478.         "rtt",        dortt,            0, 3,    "tcp rtt <tcb> <val>",
  479.         "status",    dotcpstat,        0, 0,    NULLCHAR,
  480.         "syndata",    dosyndata,       0, 0,     NULLCHAR,
  481.         "trace",    dotcptr,        0, 0,    NULLCHAR,
  482.         "window",    dowindow,        0, 0,    NULLCHAR,
  483.         NULLCHAR,
  484.     };
  485.     return subcmd(Tcpcmds,argc,argv,p);
  486. }
  487.  
  488.